﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using ControleRepresentante.Logic;
using ControleRepresentante.Logic.Models;
using ControleRepresentante.Logic.Repositories;
using ControleRepresentante.Logic.Repositories.SearchExtensions;
using ControleRepresentante.Logic.Statistics;
using WebSite.Controllers.ControllerExtensions;
using WebSite.ViewModels.DetailsViewModels;
using WebSite.ViewModels.EditViewModels;
using WebSite.ViewModels.IndexViewModels;
using Attribute = ControleRepresentante.Logic.Models.Attribute;

namespace WebSite.Controllers
{
    public class TransportadoraController : UsuariosHolderControllerBase<ITransportadoraRepository, Transportadora, StatisticsBase>
    {
        public TransportadoraController(IRepositoryProvider repositoryProvider, ISessionConfiguration sessionConfiguration, IControllerExtensionProvider controllerExtensionProvider)
            : base(repositoryProvider, sessionConfiguration, controllerExtensionProvider)
        {
        }

        protected override bool CanDelete(Transportadora model, out string message)
        {
            if (model.Pedidos.Any())
            {
                message = "Transportadora nao pode ser excluida porque possui pedidos associados a ela.";
                return false;
            }

            if (model.Users.Any())
            {
                message = "Transportadora não pode ser excluida porque possui usuários com filtros.";
                return false;
            }

            return base.CanDelete(model, out message);
        }

        protected override void RegisterIndexColumns(IIndexColumnsProvider indexColumnsProvider)
        {
            base.RegisterIndexColumns(indexColumnsProvider);
            indexColumnsProvider.SetDefaultColumns(
                indexColumnsProvider.RegisterColumn("Nome", TransportadoraIndexColumns.Nome, true),
                indexColumnsProvider[DetailsHolderIndexColumns.Telefone]);
        }

        protected override Area? Area { get { return ControleRepresentante.Logic.Models.Area.Transportadoras; } }

        protected override IAttributeHolderIndexViewModel GetAttributeHolderIndexViewModel(StatisticsBase statistics)
        {
            return new TransportadoraIndexViewModel(HasPermission(ControleRepresentante.Logic.Models.Area.Pedidos, Operacao.Create));
        }

        protected override AttributeHolderEditViewModel GetEditViewModel()
        {
            return new TransportadoraEditViewModel();
        }

        protected override AttributeType AttributeType { get { return AttributeType.Transportadora; } }

        protected override string CreateForActionName
        {
            get { return "CreateForTransportadora"; }
        }

        protected override UsuariosHolderDetailsViewModel DoGetUsuariosHolderDetailsViewModel(Transportadora model)
        {
            return new TransportadoraDetailsViewModel();
        }

        public ActionResult Search(string nome, string cidade, string bairro, FormCollection formCollection)
        {
            EnsureHasPermission(Operacao.View);

            formCollection.Add(Request.QueryString);

            IAttributeRepository attributeRepository = RepositoryProvider.GetRepository<IAttributeRepository>();
            Dictionary<Attribute, string> attributeMap = GetAttributeMap(attributeRepository, formCollection);
            ISearchExtension[] searchExtensions = GetSearchExtensions(formCollection);

            StatisticsBase statistics;
            IEnumerable<Transportadora> models = Repository.GetModels(nome, cidade, bairro, attributeMap, searchExtensions, out statistics, GetPage());

            return Index(models, statistics, formCollection, x =>
                                                                           {
                                                                               TransportadoraIndexViewModel transportadoraIndexViewModel = (TransportadoraIndexViewModel) x;
                                                                               SetAttributeSearchValues(transportadoraIndexViewModel, attributeMap);
                                                                               SetDetailsSearchValues(transportadoraIndexViewModel, cidade, bairro);
                                                                               transportadoraIndexViewModel.NomeBuscaValue = nome;
                                                                           });
        }

        [HttpPost]
        public ActionResult Create(string nome, FormCollection formCollection = null)
        {
            EnsureHasPermission(Operacao.Create);
            if (TryUpdateTransportadora(nome, formCollection))
            {
                try
                {
                    Repository.AddModel(Model);
                    Guid transportadoraId = Model.Id;
                    Model = null;
                    return RedirectToAction("Details", transportadoraId);
                }
                catch (RepositoryException<TransportadoraError> e)
                {
                    switch (e.Error)
                    {
                        case TransportadoraError.DuplicatedNome:
                            ModelState.AddModelError("Nome", "Nome duplicado");
                            break;
                        default:
                            throw;
                    }
                }
            }
            return Create(false);
        }

        [HttpPost]
        public ActionResult Edit(string nome, FormCollection formCollection = null)
        {
            EnsureHasPermission(Operacao.Update);
            if (TryUpdateTransportadora(nome, formCollection))
            {
                try
                {
                    Repository.UpdateModel(Model);
                    Guid transportadoraId = Model.Id;
                    Model = null;
                    return RedirectToAction("Details", transportadoraId);
                }
                catch (RepositoryException<TransportadoraError> e)
                {
                    switch (e.Error)
                    {
                        case TransportadoraError.DuplicatedNome:
                            ModelState.AddModelError("Nome", "Nome duplicado");
                            break;
                        default:
                            throw;
                    }
                }
            }
            return Edit();
        }

        private bool TryUpdateTransportadora(string nome, FormCollection formCollection)
        {
            Model.Nome = nome;

            UpdateAttributesToModel(formCollection);

            ModelState.Clear();
            if (String.IsNullOrEmpty(Model.Nome) ||
                Model.Nome.Trim() == String.Empty)
            {
                ModelState.AddModelError("Nome", "*");
            }

            ExtensionsUpdateModel(formCollection);

            return ModelState.IsValid;
        }
    }
}
